<?php defined('SYSPATH') or die('No direct script access.');

class Task_Model extends Auto_Modeler
{
	// Database table name
	protected $table_name = 'queue';
	
	// Database fields and default values
	protected $data = array('id'          => '',
	                        'application' => '',
	                        'class'       => '',
	                        'method'      => '',
	                        'params'      => '',
	                        'priority'    => 5
	                        );

	public function __construct($id = NULL)
	{
		parent::__construct($id);
		$this->table_name = Config::item('queue.table_name');
		$this->db = new Database('queue');
	}

	/**
	 * Scans the queue to see if we have any items. We need this method because when pcntl_fork() happens, the DB connection gets lost.
	 *
	 * @return boolean
	 */
	public static function has_items()
	{
		// Get the highest priority task in the queue
		$db = new Database('queue');
		$task = $db->from(Config::item('queue.table_name'))->orderby('priority', 'DESC')->limit(1)->get()->result(TRUE, __CLASS__);
		if (count($task))
			return TRUE;

		return FALSE;
	}
	
	/**
	 * Scans the queue and if there is a result, returns the task. Tasks with the same priority are returned in the FIFO order.
	 * 
	 * @return object
	 */
	public function scan()
	{
		// Get the highest priority task in the queue
		$task = $this->db->from($this->table_name)->orderby('priority', 'DESC')->limit(1)->get()->result(TRUE, __CLASS__);
		if (count($task))
			return $task->current();

		return FALSE;
	}
	
	/**
	 * Runs the loaded task
	 * 
	 */
	public function execute()
	{
		// Load the application
		$old_module_list = Config::item('core.modules');
		Config::set('core.modules', array_merge($old_module_list, array($this->data['application'])));
		if (Kohana::auto_load($this->data['class']))
		{
			// Delete it from the queue
			$this->delete();

			$class = new $this->data['class'];

			// Run the task
			call_user_func_array(array($class, $this->data['method']), unserialize($this->data['params']));
			Log::add('info', 'Ran '.$this->data['class'].'->'.$this->data['method']);

			// Restore the module list
			Config::set('core.modules', $old_module_list);
			unset($class);
		}
		else
		{
			Log::add('info', $this->data['class'].' not found. Aborting.');
		}
	}

	public function delete()
	{
		if ($this->data['id'])
			$this->db->delete($this->table_name, array('id' => $this->data['id']));
	}
}